package com.qdlc.p2p.biz.service;

import java.text.MessageFormat;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;

import com.qd.p2p.sina.pay.enums.AccountType;
import com.qd.p2p.sina.pay.enums.IdentityType;
import com.qd.p2p.sina.pay.param.CreateSingleHostingPayTradeParam;
import com.qd.p2p.sina.pay.param.TppSplitParam;
import com.qd.p2p.sina.pay.response.CreateSingleHostingPayTradeResponse;
import com.qd.p2p.sina.service.SinaPayService;
import com.qdlc.p2p.biz.processor.event.TppDispatchValueEvent;
import com.qdlc.p2p.common.constant.SinaConstant;
import com.qdlc.p2p.common.constant.Summary;
import com.qdlc.p2p.common.constant.TradeCode;
import com.qdlc.p2p.common.constant.TradeStatus;
import com.qdlc.p2p.common.core.queue.QueueHandlers;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.LogFactory;
import com.qdlc.p2p.common.util.MailUtil;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.dao.TppDao;
import com.qdlc.p2p.dal.dto.Tpp;
import com.qdlc.p2p.dal.dto.TppTradeLog;
import com.qdlc.p2p.dal.model.TppModel;
import com.qdlc.p2p.dal.model.TppTradeLogModel;

/**
 * 代收 代付模版类
 * <p/>
 * 还款代收
 * 还款代付
 * 回调等方法
 *
 * @author wuaj
 */
public abstract class AbstractCollectPayService {

    Logger logger = LogFactory.TRADE_LOGGER;

    @Resource
    public TppTradeService tppTradeService;

    @Resource
    public SinaPayService sinaPayService;
    
    @Resource
    public TppDao tppDao;

    public static String WEB_URL = SystemConfigHelper.getValue(SystemConfigHelper.Nid.WEB_URL);

    /**
     * 代收回调地址
     */
    public abstract String getCollectCallBackUrl();

    /**
     * 代付回调地址
     */
    public abstract String getPayCallBackUrl();

    /**
     * 代收业务名
     */
    public abstract String getCollectBusinessName();

    /**
     * 代付业务名
     */
    public abstract String getPayBusinessName();

    /**
     * 交易完成
     */
    public void tradeFinish(TppTradeLog tppTradeLog, String depositStatus, double tradeAmount, String businessName) {
        tppTradeLog.setAmount(tradeAmount); // 实际交易金额
        tppTradeLog.setTradeTime(DateUtil.getNow()); // 交易成功时间
        tppTradeService.updateTradeLog(tppTradeLog, depositStatus, businessName.concat("交易完成"));
    }

    /**
     * 交易成功
     */
    public void tradeSuccess(TppTradeLog tppTradeLog, String depositStatus, String businessName) {
        tppTradeService.updateTradeLog(tppTradeLog, depositStatus, businessName.concat("交易成功"));
    }

    /**
     * 交易失败
     */
    public void tradeFail(TppTradeLog tppTradeLog, String depositStatus, String businessName) {
        // 更新TPPLog
        tppTradeLog.setTradeTime(DateUtil.getNow()); // 还款失败时间
        tppTradeService.updateTradeLog(tppTradeLog, depositStatus, businessName.concat("交易失败"));
    }

    /**
     * 代付接口调用
     */
    public boolean payTrade(TppTradeLog tppTradeLog, Summary summary,TradeCode tradeCode,List<TppSplitParam> splits) {
        CreateSingleHostingPayTradeResponse response = null;
        String orderNo = tppTradeLog.getOrderNo();
        double money = tppTradeLog.getMoney();
		try {
            // 调用代付接口
            CreateSingleHostingPayTradeParam param = new CreateSingleHostingPayTradeParam();
            param.setOutTradeNo(orderNo)
                    .setPayeeIdentityId(tppTradeLog.getToTppUserCustId())
                    .setPayeeIdentityType(IdentityType.UID)
                    .setOutTradeCode(tradeCode)
                    .setAmount(money)
                    .setSummary(summary.getSummaryType() + tppTradeLog.getOrderNo())
                    .setSplitList(splits)
                    .setAccountType(AccountType.SAVING_POT)
                    .setNotifyUrl(getPayCallBackUrl());
            response = sinaPayService.createSingleHostingPayTrade(param);
        } catch (Exception ex) {
            // do nothing
        }
        // 代付调用成功
        if (response != null && response.success()) {
            updateOrderRemark(tppTradeLog, getPayBusinessName().concat("提交成功"));
        } else {
            String message = response == null ? "RPC调用失败" : getPayBusinessName().concat(MessageFormat.format("代付失败!reqStatus:{0} reqErrorMessage:{1} resCode:{2} resMessage:{3}",
                    response.getReqStatus(), response.getReqErrorMessage(), response.getResponseCode(),
                    response.getResponseMessage()));
            String responseMessage = response == null ? "RPC调用失败" : response.getResponseMessage();
            logger.info(message);

            // 置为废单
            tppTradeLog.setTradeStatus(TradeStatus.TRADE_STATUS_INVALID.getStatus());
            updateOrderRemark(tppTradeLog, getPayBusinessName().concat("提交失败-" + responseMessage));
            
            // 保存调度任务信息
            Tpp tpp = new Tpp();
            tpp.setStatus(TppModel.STATUS_FAIL);
            tpp.setServiceType(TppModel.DOREPAY);
            tpp.setTppType(SinaConstant.TRADE_SERVICE_REPAY);
            tpp.setTppUserCustId(tppTradeLog.getTppUserCustId());// 借款人托管账户ID
            tpp.setMoney(money);
            tpp.setOrderId(orderNo);
            tpp.setOrderDate(DateUtil.dateStr7(tppTradeLog.getAddTime()));
            tpp.setExtended(tppTradeLog.getBorrowRepaymentId()+"");// 还款ID
            tpp.setTradeType(tppTradeLog.getTradeType());
            tpp.setRespDesc(getPayBusinessName().concat("提交失败-" + responseMessage));
            tpp.setAddTime(DateUtil.getNow());
            tpp.setTppBorrowId(tppTradeLog.getBorrowId()+"");// 标ID
            tppDao.save(tpp);
            
            // 调度任务交由队列处理(延时处理)
            if (tppTradeLog.getAutoDispatch() != TppTradeLogModel.IS_AUTO) {// 防止重复处理
            	TppModel tppModel = TppModel.instance(tpp);
            	TppDispatchValueEvent tppDispatchValueEvent = new TppDispatchValueEvent();
            	tppDispatchValueEvent.setTppModel(tppModel);
                QueueHandlers.put(tppDispatchValueEvent);
            }

            // 解决容错地址
            //String reCallUrl = String.format(NotifyUrl.RE_RED_ENVELOPE_PAY_URL, WEB_URL, tppTradeLog.getAssociateOrderId());
            MailUtil.sendMail(getPayBusinessName().concat("提交失败-" + responseMessage), getPayBusinessName().concat("提交失败"), "");
            return false;
        }
        return true;
    }

    /**
     * 更新订单Remark
     */
    public void updateOrderRemark(TppTradeLog tppTradeLog, String remark) {
        // 修改描述
        tppTradeLog.setRemark(remark);
        tppTradeService.updateTradeLog(tppTradeLog, null, remark);
    }
}
